package coloring.main;

import static coloring.utils.Util.colorNumber;

import org.jgrapht.Graph;

import coloring.MyDefaultEdge;
import coloring.alg.GenerateGraph;
import coloring.alg.GreedyColoring;
import coloring.checking.ColoringCheck;
import coloring.vertex.Vertex;
import dot.Export;
import dot.Import;

/**
 * Main class for checking how algorithm works
 * 
 * @author Croaker
 * 
 */
public class Main {

	public static void main(String[] args) throws Exception {
		Main main = new Main();
		if (args.length == 0 || main.containsHelp(args)) {
			System.out
					.println("Usage: \n"
							+ "\t -help  prints this help message \n"
							+ "\t <path to .dot file> [name of generated dot.file] [-options]  - by default outputfile is Graph.dot\n"
							+ "or \n"
							+ "\t -randomize:<number of verteses>,<number of edges> [name of generated dot.file] [-options]  - with no spaces at randomize\n"
							+ "\n"
							+ "where options include:\n"
							+ "\t -addinf - generates additional information in output\n"
							+ "\t -loop: <number of iterations> - minimal number of iterations\n"
							+ "\t -nocheck - if you don't want to check graph for right coloring\n");
		} else {
			try {
				Graph<Vertex, MyDefaultEdge> graph = main.constructGraph(args);
				GreedyColoring greedyColoring = new GreedyColoring(main
						.loopNumber(args));
				System.out.println("Coloring in progress, please wait...");
				long time = System.currentTimeMillis();
				graph = greedyColoring.color(graph, main.containsDashA(args));
				System.out.println("Time spent for coloring is: "
						+ (System.currentTimeMillis() - time) + " ms");
				if (!main.containsNoCheck(args)) {
					ColoringCheck coloringCheck = new ColoringCheck();
					System.out.println("Colored correctly? "
							+ coloringCheck.check(graph));
				}
				System.out.println("Finally colors: " + colorNumber(graph));

				Export export = new Export();
				if (args.length == 1 || args[1].startsWith("-")) {
					System.out
							.println("No specidied output file dectected, output data will be written to Graph.dot");
					export.exportToDot("Graph.dot", graph);
				} else {
					System.out.println("Data will be written to " + args[1]);
					export.exportToDot(args[1], graph);
				}
				System.out.println("Finished successfully");
			} catch (Exception e) {
				System.out.println("Error on processing");
			}

		}
	}

	/**
	 * Indicates if there is a -help key
	 * 
	 * @param args
	 * @return
	 */
	private boolean containsHelp(String[] args) {
		boolean contains = false;
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("-help")) {
				contains = true;
				break;
			}
		}
		return contains;
	}

	/**
	 * Checks if parameters contains option for additional(debugger) information
	 * 
	 * @param args
	 * @return
	 */
	private boolean containsDashA(String[] args) {
		boolean contains = false;
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("-addinf")) {
				System.out
						.println("You specified that you want to view additional information");
				contains = true;
				break;
			}
		}
		return contains;
	}

	/**
	 * Checks if parameters contains option for no checking
	 * 
	 * @param args
	 * @return
	 */
	private boolean containsNoCheck(String[] args) {
		boolean contains = false;
		for (int i = 0; i < args.length; i++) {
			if (args[i].equals("-nocheck")) {
				System.out
						.println("You specified that you don't want to check coloring");
				contains = true;
				break;
			}
		}
		return contains;
	}

	/**
	 * Extracts loop number form command line. Default values 10
	 * 
	 * @param args
	 * @return
	 */
	private int loopNumber(String[] args) {
		int loopNumber = 10;
		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith("-loop:")) {
				loopNumber = Integer.decode(args[i].substring(args[i]
						.indexOf(":") + 1));
				System.out
						.println("You specified that you want to set loop number as "
								+ args[i].substring(args[i].indexOf(":") + 1));
				break;
			}
		}
		return loopNumber;
	}

	/**
	 * Constructing graph by specified parameters
	 * 
	 * @param args
	 * @return
	 * @throws Exception
	 */
	private Graph<Vertex, MyDefaultEdge> constructGraph(String[] args)
			throws Exception {
		Graph<Vertex, MyDefaultEdge> graph;
		if (randomNum(args) != -1) {
			int num = randomNum(args);
			System.out.println("Generatating random graph with "
					+ args[num].substring(11, args[num].indexOf(","))
					+ " vertices and "
					+ args[num].substring(args[num].indexOf(",") + 1)
					+ " edges...");

			graph = GenerateGraph.genRandomGraph(Integer.decode(args[num]
					.substring(11, args[num].indexOf(","))), Integer
					.decode(args[num].substring(args[num].indexOf(",") + 1)));
		} else {
			System.out.println("Reading from file...");
			Import import1 = new Import();
			try {
				graph = import1.genGraphFromDot(args[0]);
			} catch (Exception e) {
				System.out
						.println("Exception on constructing graph by reading from file - first argument should be path to .dot file with elementary rules");
				throw e;
			}
		}
		return graph;
	}

	/**
	 * Return number of argument started with "-randomize:", otherwise -1
	 * 
	 * @param args
	 * @return
	 */
	private int randomNum(String[] args) {
		int index = -1;
		for (int i = 0; i < args.length; i++) {
			if (args[i].startsWith("-randomize:")) {
				index = i;
				break;
			}
		}
		return index;
	}

}
